package g11.actionutil;

import g11.dao.AppointmentDAO;
import g11.dao.AppointmentDAOImpl;
import g11.dao.DAOException;
import g11.dao.PatientDAO;
import g11.dao.PatientDAOImpl;
import g11.dao.PrescriptionDAO;
import g11.dao.PrescriptionDAOImpl;
import g11.dao.VisitationContentDAO;
import g11.dao.VisitationContentDAOImpl;
import g11.dao.VisitationDAO;
import g11.dao.VisitationDAOImpl;
import g11.model.Appointment;
import g11.model.Drug;
import g11.model.Employee;
import g11.model.Patient;
import g11.model.Prescription;
import g11.model.Visitation;
import g11.model.VisitationContent;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.HibernateException;

public class VisitationContentUtilImpl implements VisitationContentUtil {

	private Integer createVisitationContentAndPrescription(
			VisitationContent visitationContent) throws DAOException {
		Integer visitationContentId;
		VisitationContentDAO visitationContentDAO = new VisitationContentDAOImpl();
		try {
			// visitationContent.setVisitationContentId(null);
			Set<Prescription> prescriptionSet = new HashSet<Prescription>();
			if (visitationContent.getPrescriptionSet().size() > 0) {
				for (Prescription tempPrescription : visitationContent
						.getPrescriptionSet()) {
					prescriptionSet.add(tempPrescription);
				}
				visitationContent.getPrescriptionSet().clear();
			}

			visitationContentId = visitationContentDAO
					.createVisitationContent(visitationContent);

			if (prescriptionSet.size() > 0) {
				PrescriptionDAO prescriptionDAO = new PrescriptionDAOImpl();
				for (Prescription tempPrescription : prescriptionSet) {
					tempPrescription
							.setVisitationContentId(visitationContentId);
					prescriptionDAO.createPrescription(tempPrescription);
				}
			}
		} catch (HibernateException e) {
			throw new DAOException(e.getMessage());
		}

		return visitationContentId;
	}

	@Override
	public List<VisitationContent> getLatestVisitationContentListByVisitationList(
			List<Visitation> visitationList) throws Exception {
		List<VisitationContent> returnVisitationContentList = new ArrayList<VisitationContent>();
		VisitationContentDAO visitationContentDAO = new VisitationContentDAOImpl();
		try {
			for (Visitation tempVisitation : visitationList) {
				returnVisitationContentList.add(visitationContentDAO
						.getCurrentVisitationContent(tempVisitation));
			}
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
		return returnVisitationContentList;
	}

	@Override
	public Integer updateVisitationContent(VisitationContent visitationContent)
			throws Exception {

		Integer visitationContentId;
		try {

			VisitationDAO visitationDAO = new VisitationDAOImpl();
			Visitation latestVisitation = visitationDAO
					.getCurrentVersionOfVisitation(visitationContent
							.getVisitation().getVisitationId());

			latestVisitation.setCurrentVersion(latestVisitation
					.getCurrentVersion() + 1);// increment the version for
												// latest visitation
			visitationContent.setVersion(latestVisitation.getCurrentVersion());
			latestVisitation.setCurrentVersion(visitationContent.getVersion());
			java.util.Date date = new java.util.Date();
			visitationContent.setLastModified(new Timestamp(date.getTime()));
			visitationContent.setVisitation(latestVisitation);

			visitationContentId = this
					.createVisitationContentAndPrescription(visitationContent);
			visitationDAO.updateCurrentVersion(latestVisitation);
		} catch (DAOException e) {
			throw new DAOException(e.getMessage());
		}
		return visitationContentId;
	}

	@Override
	public List<VisitationContent> getLatestVisitationContentByDrugForDoctor(
			Drug drug, Employee doctor) throws Exception {
		List<VisitationContent> returnVisitationContentList = new ArrayList<VisitationContent>();
		List<VisitationContent> tempVisitationContentList = new ArrayList<VisitationContent>();
		List<Visitation> tempVisitationList = new ArrayList<Visitation>();
		try {
			// 1. get visitation for doctor
			VisitationUtil visitationUtil = new VisitationUtilImpl();
			tempVisitationList = visitationUtil.getVisitationByDoctor(doctor);
			// 2. get latest visitationcontent for each visitation
			tempVisitationContentList = this
					.getLatestVisitationContentListByVisitationList(tempVisitationList);
			// 3. for each visitationcontent, check if it contains the drug, by
			// comparing the drug id.
			// if so, add the visitationcontent into the return list.
			for (VisitationContent tempVisitationContent : tempVisitationContentList) {
				for (Prescription tempPrescription : tempVisitationContent
						.getPrescriptionSet()) {
					if (tempPrescription.getDrugId() == drug.getDrugId()) {
						returnVisitationContentList.add(tempVisitationContent);
					}
				}
			}

		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}

		return returnVisitationContentList;
	}

	@Override
	public List<VisitationContent> getLatestVisitationContentByKeywordForDoctor(
			Employee doctor, String keyword, int attribute) throws Exception {
		List<VisitationContent> doctorsLatestVisitationContentList = new ArrayList<VisitationContent>();
		List<VisitationContent> retrievedVisitationContentListByKeyword = new ArrayList<VisitationContent>();
		List<VisitationContent> returnVisitationContentList = new ArrayList<VisitationContent>();
		try {
			// 1. retrieve all the latest visitationcontent for the doctor
			List<Visitation> tempVisitationList = new ArrayList<Visitation>();
			VisitationUtil visitationUtil = new VisitationUtilImpl();
			tempVisitationList = visitationUtil.getVisitationByDoctor(doctor);
			doctorsLatestVisitationContentList = this
					.getLatestVisitationContentListByVisitationList(tempVisitationList);
			// 2. get VisitationContentList by keyword and attribute
			VisitationContentDAO visitationContentDAO = new VisitationContentDAOImpl();
			retrievedVisitationContentListByKeyword = visitationContentDAO
					.getVisitationContentByKeyword(keyword, attribute);
			// 3. compare the two lists, store those matched into returnlist
			for (VisitationContent tempOuterVisitationContent : retrievedVisitationContentListByKeyword) {
				for (VisitationContent tempInnerVisitationContent : doctorsLatestVisitationContentList) {
					if (tempInnerVisitationContent.getVisitationContentId() == tempOuterVisitationContent
							.getVisitationContentId()) {
						returnVisitationContentList
								.add(tempInnerVisitationContent);
					}
				}

			}
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
		return returnVisitationContentList;
	}

	@Override
	public Integer createVisitationContentFromAppointment(
			Appointment appointment, VisitationContent visitationContent)
			throws Exception {
		Integer vcId;

		try {

			VisitationDAO visitationDao = new VisitationDAOImpl();
			AppointmentDAO appointmentDao = new AppointmentDAOImpl();
			visitationDao.createVisitationFromAppointment(appointment);
			Visitation visitation = visitationDao
					.getCurrentVersionOfVisitation(appointment
							.getAppointmentId());
			visitationContent.setVisitation(visitation);
			java.util.Date date = new java.util.Date();
			visitationContent.setLastModified(new Timestamp(date.getTime()));
			visitationContent.setVersion(visitation.getCurrentVersion());
			vcId = this
					.createVisitationContentAndPrescription(visitationContent);
			Byte visited = 1;
			appointment.setStatus(visited);
			appointmentDao.updateAppointment(appointment);
			Patient patient = new Patient();
			PatientDAO patientDAO = new PatientDAOImpl();
			patient = patientDAO.getPatientById(appointment.getPatient()
					.getId());
			patient.setLastVisitTime(appointment.getAppointmentDate());
			patientDAO.updatePatient(patient);

		} catch (DAOException e) {
			throw new Exception(e.getMessage());
		}

		return vcId;

	}

	@Override
	public VisitationContent getVisitationContentByVisitationId(
			Integer visitationId) throws Exception {
		VisitationDAOImpl vdi = new VisitationDAOImpl();
		VisitationContentDAOImpl vcdi = new VisitationContentDAOImpl();
		AppointmentDAOImpl appDao = new AppointmentDAOImpl();
		Visitation retrievedVisitation = new Visitation();

		try {
			retrievedVisitation = vdi
					.getCurrentVersionOfVisitation(visitationId);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}

		VisitationContent retrievedVisitationContent = new VisitationContent();
		try {
			retrievedVisitationContent = vcdi
					.getCurrentVisitationContent(retrievedVisitation);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}

		if (retrievedVisitationContent != null) {
			Appointment appointment = new Appointment();
			try {
				appointment = appDao.getAppointmentById(retrievedVisitation
						.getVisitationId());
			} catch (DAOException e) {
				e.printStackTrace();
				throw new Exception(e.getMessage());
			}

			retrievedVisitation.setAppointment(appointment);
			retrievedVisitationContent.setVisitation(retrievedVisitation);

		} else {
			throw new Exception("Cannot retrieve VisitationContent");
		}

		return retrievedVisitationContent;
	}

}
